#include <system.h>

/*
 * 0x01 = Alt
 * 0x02 = Ctrl
 * 0x04 = Shift
 * 0x08 = Num Lock
 * 0x10 = Caps Lock
 * 0x20 = Scroll Lock
 */
unsigned char kbmetakeys = 0;


unsigned char kbus[256] =
{
 0, 27, '1', '2', '3', '4', '5', '6', '7', '8',	/* 9 */
 '9', '0', '-', '=', '\b' /* Backspace */, '\t' /* Tab */, 'q', 'w', 'e', 'r',	/* 19 */
  't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',	/* Enter key */
 0,			/* 29   - Control */
  'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',	/* 39 */
 '\'', '`',   0,		/* Left shift */
 '\\', 'z', 'x', 'c', 'v', 'b', 'n',			/* 49 */
  'm', ',', '.', '/',   0,				/* Right shift */
  '*',
 0,	/* Alt */
  ' ',	/* Space bar */
 0,	/* Caps lock */
 0,	/* 59 - F1 key ... > */
 0,   0,   0,   0,   0,   0,   0,   0,
 0,	/* < ... F10 */
 0,	/* 69 - Num lock*/
 0,	/* Scroll Lock */
 0,	/* Home key */
 0,	/* Up Arrow */
 0,	/* Page Up */
  '-',
 0,	/* Left Arrow */
 0,
 0,	/* Right Arrow */
  '+',
 0,	/* 79 - End key*/
 0,	/* Down Arrow */
 0,	/* Page Down */
 0,	/* Insert Key */
 0,	/* Delete Key */
 0,   0,   0,
 0,	/* F11 Key */
 0,	/* F12 Key */
 0,	/* All other keys are undefined */
};

void keyboard_install()
{
#if _Verbose_Init_
 vga_printstr("Keyboard...");
#endif

 irq_install_handler(1,&keyboard_handler);

#if _Verbose_Init_
 vga_printstr("initialized.\n");
#endif
}

/* Handles the keyboard interrupt */
void keyboard_handler(struct regs* r)
{
 unsigned char scancode;

 /* Read from the keyboard's data buffer */
 scancode = inportb(0x60);

 /* If the top bit of the byte we read from the keyboard is
 *  set, that means that a key has just been released */
 if (scancode & 0x80)
 {
  if(scancode == (0x80 | 42) || scancode == (0x80 | 54))
  {
   kbmetakeys &= 0x3B; // Disables the shift bit
  }
 }
 else
 {
 /* Here, a key was just pressed. Please note that if you
 *  hold a key down, you will get repeated key press
 *  interrupts. */

 /* Just to show you how this works, we simply translate
 *  the keyboard scancode into an ASCII value, and then
 *  display it to the screen. You can get creative and
 *  use some flags to see if a shift is pressed and use a
 *  different layout, or you can add another 128 entries
 *  to the above layout to correspond to 'shift' being
 *  held. If shift is held using the larger lookup table,
 *  you would add 128 to the scancode when you look for it */

  if(scancode == 42 || scancode == 54)
  {
   kbmetakeys &= 0x04; // Enables the shift bit
  }

  
  vga_printchar(kbus[scancode]);
 }
}

/*
 * 0x01 = Scroll Lock
 * 0x02 = Num Lock
 * 0x04 = Caps Lock
 */

void keyboard_setlights(unsigned char lights)
{
 while((inportb(0x64)&2) != 0);
 outportb(0x60,0xED);
 outportb(0x60,lights);
}